#include "Tcp_Client.hpp"
#include "Sock.hpp"
#include <iostream>
#include "Protocol.hpp"

using namespace Protocal_ns;

static void Usage(std::string proc)
{
    std::cout << "Usage:\n\t" << proc << "serverip serverport\n"
              << std::endl;
}

enum
{
    LEFT,
    OPER,
    RIGHT
};

Request Parse(const std::string &line)
{
    std::string left, right;
    char op;

    int STATUS = LEFT;
    int i = 0;
    // std::cout << "ready" << std::endl;
    while (i < line.size())
    {
        if (line[i] == ' ')
            i++;
        else
        {
            switch (STATUS)
            {
            case LEFT:
                if (isdigit(line[i]))
                    left.push_back(line[i++]);
                else
                    STATUS = OPER;
                break;
            case OPER:
                op = line[i++];
                STATUS = RIGHT;
                break;
            case RIGHT:
                if (isdigit(line[i]))
                    right.push_back(line[i++]);
                break;
            }
        }
    }
    // std::cout << "Left: " << left << std::endl;
    // std::cout << "Rght: " << right << std::endl;
    Request req;
    req._x = stoi(left);
    req._y = stoi(right);
    req._op = op;

    return req;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }

    std::string ip = argv[1];
    uint16_t port = atoi(argv[2]);
    Sock sock;
    sock.Socket();
    int n = sock.Connect(ip, port);
    if (n != 0)
        return 1;

    std::string buffer;
    while (true)
    {
        Request rq;
        memset(&rq, 0, sizeof(rq));

        std::cout << "Enter # ";
        std::string line;
        std::getline(std::cin, line);
        rq = Parse(line);

        // std::cout << "data1# ";
        // std::cin >> rq._x;
        // std::cout << "data2# ";
        // std::cin >> rq._y;
        // std::cout << "op# ";
        // std::cin >> rq._op;

        // std::cout << "test: " << rq._x << " " << rq._op << " " << rq._y << std::endl;

        std::string sendstring;
        rq.Serialize(&sendstring);          // 序列化
        sendstring = AddHeader(sendstring); // 添加报头

        // std::cout << "message ready to send" << std::endl;

        send(sock.Fd(), sendstring.c_str(), sendstring.size(), 0);

        // std::cout << "message already send" << std::endl;

        // 获取结果
        std::string package;
        int n = 0;
    START:
        // std::cout << "ready to enter" << std::endl;
        n = ReadPackage(sock.Fd(), buffer, &package);
        if (n == 0)
            goto START;
        else if (n < 0)
            break;

        // 去报头
        package = RemoveHeader(package, n);

        // 反序列化
        Response resp;
        resp.DeSerialize(package);
        // std::cout << "result: " << resp._result << "[" << resp._code << "]" << std::endl;

        if (resp._code == 0)
            std::cout << "result: " << resp._result << "[" << resp._code << "]" << std::endl;
        else if (resp._code == 1)
            std::cout << "/ can not with 0" << std::endl;
        else if (resp._code == 2)
            std::cout << "mod can not with 0" << std::endl;
        else
        {
            logmessage(WARNING, "unknow error");
            std::cout << "unknow error" << std::endl;
        }
    }
}